package com.wx.api.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wx.api.config.WxPayConfig;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.Signature;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;

/**
 * 微信支付工具类
 */
@Component
public class WxPayUtil {
    private static final Logger log = LoggerFactory.getLogger(WxPayUtil.class);

    private static WxPayConfig wxPayConfig;

    public static WxPayConfig getWxPayConfig() {
        return wxPayConfig;
    }
    @Autowired
    public static void setWxPayConfig(WxPayConfig wxPayConfig) {
        WxPayUtil.wxPayConfig = wxPayConfig;
    }

    /**
     * 获取签名方法
     * @param message
     * @return
     * @throws Exception
     */
    public static String sign(byte[] message , PrivateKey privateKey) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 生成32位订单号
     * 17位时间戳 + 3位随机数 + 11位手机号
     * @param mobile
     * @throws Exception
     */
    public static String genOrderId(String mobile){
        // 时间（精确到毫秒）
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String localDate = LocalDateTime.now().format(ofPattern);
        // 3位随机数
        String randomNumeric = RandomStringUtils.randomNumeric(3);
        return localDate + randomNumeric + mobile;
    }

    /**
     * 验签
     * @param serialNumber
     * @param message
     * @param signature
     * @return
     */
    public static Boolean signVerfier(String serialNumber, String message, String signature){
        // 私钥
        //            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
//                    new ByteArrayInputStream(getWxPayConfig().getPrivateKey().getBytes("utf-8")));
        PrivateKey merchantPrivateKey = getWxPayConfig().getPrivateKey();
        //使用自动更新的签名验证器，不需要传入证书
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(getWxPayConfig().getMchid(), new PrivateKeySigner(getWxPayConfig().getMerchantSerialNumber(), merchantPrivateKey)),
                getWxPayConfig().getApiV3Key().getBytes(StandardCharsets.UTF_8));

        return verifier.verify(serialNumber, message.getBytes(StandardCharsets.UTF_8), signature);
    }

    /**
     * 解密
     * @param body
     * @return
     */
    public static String decryptOrder(String body){
        AesUtil aesUtil = new AesUtil(getWxPayConfig().getApiV3Key().getBytes(StandardCharsets.UTF_8));
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode jsonNode = objectMapper.readTree(body);
            JsonNode resource = jsonNode.get("resource");
            String nonce = resource.get("nonce").textValue();
            String ciphertext = resource.get("ciphertext").textValue();
            // 数据密文
            String associated_data = resource.get("associated_data").textValue();
            return aesUtil.decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 读取请求数据流
     * @param request
     * @return
     */
    public static String getRequestBody(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        try (ServletInputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            log.error("读取数据流异常:{}", e);
        }
        return sb.toString();

    }
}
